
#include "Graphics.h"

/*----------------------------------------------------------------------------*/
Graphics::Graphics(int width, int height, Sim* pSim) {
	screenWidth = width;
	screenHeight = height;

	sim = pSim;
	cam = Camera();
	viewCam = Camera();
	
	targeting = false;

	//make some space for moon view thing
	moonViewHeight = MOON_VIEW_H;

	createWindow("Senior Project", width, height, 0, 0, false);
	initialize();


	startWindow();
}

/*----------------------------------------------------------------------------*/
void Graphics::initialize() {	

	followBodyIndex = 1;
	keyRightDown = false;
	keyLeftDown = false;
	camAtMoon = false;
	cameraMoveMode = false;
	cam.setZoomDist(10.0);
	cam.setZoomMinDist(1.0f);

	createGeosphereDisplayLists();

	//SETUP CAMERA FOR ORBITAL BODY VIEWPORT
	//determine how much space we need since we want a nice fit
	//for the viewscreen and the width can vary drastically
	//depending on the number and radii of the moons
	//the width we need is the diameter of all the orbital bodies + 1 each for spacing
	lineupWidth = sim->getTotalRad()*2 + 1*sim->getNumOrbitalBodies();

	viewCam.setZoomMinDist(1.0f);
	Vec3f targ = Vec3f(0, 0, 0);
	viewCam.setTargetPos(targ);
	viewCam.setEyeVec(Vec3f(0, 0, 2));
	viewCam.setUpVec(Vec3f(0, 1, 0));
	if (lineupWidth/4 < 2.5)
		viewCam.setZoomDist(2.5);	
	else
		viewCam.setZoomDist(lineupWidth/5);	


	dlStars = -1;
	numStars = 3000;
	stars = new Star[numStars];

	lightPos[0] = 100;
	lightPos[1] = 150;
	lightPos[2] = 200;
	lightPos[3] = 0;
	
	ones[0] = ones[1] = ones[2] = ones[3] = 1.0;
	mids[0] = mids[1] = mids[2] = 0.5; mids[3] = 1.0;
	zeros[0] = zeros[1] = zeros[2] = 0.0; zeros[3] = 1.0;
	alphas[0] = alphas[1] = alphas[2] = 1.0; alphas[3] = 0.0;
	blues[0] = 0.0f; blues[1] = 0.65f; blues[2] = blues[3] = 1.0f;
	reds[0] = 1.0f; reds[1] = 0.3f; reds[2] = 0; reds[3] = 1.0f;

	tt = TerrainTexture();
	moonTexture = tt.getTextureId();

	//////////////////////////////////////


	glEnable(GL_LIGHTING);
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, mids);
	glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE);
	glLightfv(GL_LIGHT1, GL_AMBIENT, zeros);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, ones);
	glLightfv(GL_LIGHT1, GL_POSITION, lightPos);
	glLightfv(GL_LIGHT1, GL_SPECULAR, ones );
	glEnable(GL_LIGHT1);
	
	glEnable(GL_TEXTURE_2D);

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glClearColor(0,0,0,0);

	initNebula();

	targSphere.init(&cam);
	missilesFired = 0;
	targetPos = Vec3f(0,0,0);
	
	//set up picker...for picking moons...definitely not for 
	//picking my nose...nope...not at all...
	pk.init(this);

	//set up another picker for the viewscreen
	viewPk.init(this);
	
	//init the OSD
	osd.initOSD(screenWidth, screenHeight, moonViewHeight);

	mouseFunc(0, 1, 0, 0);
}

/*----------------------------------------------------------------------------*/
void Graphics::initNebula(){

	nebulaSphere = gluNewQuadric();

	//stream to read the texture file from
	std::ifstream fin ("skins/nebula.tex", std::ios::in | std::ios::binary);

	int x, y;
	//extract image size
	fin.read((char*)&x, sizeof(x));
	fin.read((char*)&y, sizeof(y));

	//bind the bitmap in OpenGL
	glGenTextures(1, &nebulaT);
	glBindTexture(GL_TEXTURE_2D, nebulaT);


	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

	char* temp = new char[x * y * 4];

	//extract targa data
	fin.read((char*)temp, x * y * 4);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y,
		0, GL_RGBA, GL_UNSIGNED_BYTE, temp);

	delete[] temp;
	fin.close();

}


////////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
void Graphics::displayFunc() {

	sim->update();

	if (osd.isTarget())
		toggleTargeting();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glLoadIdentity();	

	

	if (!viewPk.isPicking()) {
		Vec3f center = *(sim->getOrbitalBody(0)->getLoc());
		Vec3f targ = *(sim->getOrbitalBody(followBodyIndex)->getLoc());
		if ( camAtMoon ) { Vec3f temp = center; center = targ; targ = temp; }
		cam.setTargetPos(targ);
		cam.update();

		glLightfv(GL_LIGHT1, GL_POSITION, lightPos);			

		draw();
	}

	if (targeting)
		targSphere.drawTargetSys(*(sim->getOrbitalBody(followBodyIndex)->getLoc()));


	if (!pk.isPicking() && !targeting)
	{
		

		glDisable(GL_BLEND);
		drawViewScreen();	
		glEnable(GL_BLEND);

		if (!viewPk.isPicking())
			osd.drawOSD();
	}

	if (!viewPk.isPicking()) {
		drawPickingSpheres();
	}

	swapBuffers();
}

/*----------------------------------------------------------------------------*/
void Graphics::reshapeFunc(int width, int height) {
	if ( !height ) { height = 1; }

	screenWidth = width;
	screenHeight = height;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glViewport(0,moonViewHeight,width,height-(moonViewHeight));
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(57.0, width/(float)(height-moonViewHeight), 0.1, 2000.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

/*----------------------------------------------------------------------------*/
void Graphics::idleFunc() {
	postRedisplay();
}

/*----------------------------------------------------------------------------*/
void Graphics::keyboardFunc(unsigned char key, int x, int y) {
	//cout << "keyboardFunc: " << key << " [" << (int)key << "] (" << x << ", " << y << ")" << endl;

	if ( key == KEY_UP ) { cam.incZoomDist( -0.5f ); }
	if ( key == KEY_DOWN ) { cam.incZoomDist( 0.5f ); }
	
	if ( key == KEY_RIGHT ) { 
		followBodyIndex = (followBodyIndex+1)%(sim->getNumOrbitalBodies()-1) + 1;
		Vec3f targ = *(sim->getOrbitalBody(followBodyIndex)->getLoc());
		const Vec3f* vel = sim->getOrbitalBody(followBodyIndex)->getVel();
		cam.moveToNewTarget(targ, vel, 240);
	}
	if ( key == KEY_LEFT ) {
		if ( --followBodyIndex < 1 ) { followBodyIndex = sim->getNumOrbitalBodies()-1; }
		Vec3f targ = *(sim->getOrbitalBody(followBodyIndex)->getLoc());
		const Vec3f* vel = sim->getOrbitalBody(followBodyIndex)->getVel();
		cam.moveToNewTarget(targ, vel, 240);
	}

	if ( key == KEY_PAGE_UP ) { camAtMoon = false; }
	if ( key == KEY_PAGE_DOWN ) { camAtMoon = true; }

	if ( key == 't' ) { 
		toggleTargeting();
	}

	if ( key == 'f' && targeting) {
		Vec3f targ = *(sim->getOrbitalBody(followBodyIndex)->getLoc());
		Missile* m;
		m = new Missile(3);
		sim->createMissileBody(++missilesFired, m, targ, targetPos); 
	}
}

/*----------------------------------------------------------------------------*/
void Graphics::toggleTargeting() {

	targeting = !targeting; 
	if (targeting)
	{
		camAtMoon = true;
		//get rid of moon view area
		moonViewHeight = 0;
		oldZoom = cam.getZoomDist();
		cam.setZoomDist(100);
		reshapeFunc(screenWidth, screenHeight);			
	}
	else
	{
		camAtMoon = false;
		moonViewHeight = MOON_VIEW_H;
		cam.setZoomDist(oldZoom);
		reshapeFunc(screenWidth, screenHeight);			
	}

}

/*----------------------------------------------------------------------------*/
void Graphics::mouseFunc(int button, int state, int x, int y) {
	//cout << "mouseFunc: " << button << ", " << state << ", " << x << ", " << y << endl;
	// button: leftclick=0, rightclick = 2
	// state: pressed=0, released = 1
	if (targeting){
		targetPos = targSphere.mouseClick(button, state, x, y);
	}
	else{
		if ( button == 2 ) { 
			cameraMoveMode = !state;
			if ( cameraMoveMode ) { cam.startMouseRotation(); }
		}
		else if (button == 0) {			
			if (!osd.checkClick(button, state, x, y) && state == 0) {
				//if on main screen
				if (y < screenHeight-moonViewHeight) 
				{
					//see if we got a moon
					int pickedBody = pk.get_object(x, y, moonViewHeight);
					//set camera to follow the picked moon
					if (pickedBody && pickedBody != 1)
					{
						pickedBody--;
						//printf("pb: %d\n", pickedBody);
						Vec3f targ = *(sim->getOrbitalBody(pickedBody)->getLoc());
						const Vec3f* vel = sim->getOrbitalBody(pickedBody)->getVel();
						cam.moveToNewTarget(targ, vel, 80);
						followBodyIndex = pickedBody;
					}
				}
				//else in view screen
				else
				{
					//save the current projection matrix
					glGetFloatv(GL_PROJECTION_MATRIX, proj_mat);
					//save the current model view matrix
					glGetFloatv(GL_MODELVIEW_MATRIX, modl_mat);
					//save the current viewport
					glGetIntegerv (GL_VIEWPORT, viewport);

					//set up the viewport and proj matrix
					glViewport (0, 0, screenWidth, moonViewHeight);
					glMatrixMode (GL_PROJECTION);
					glLoadIdentity ();
					gluPerspective(25.0, screenWidth/(float)moonViewHeight, 0.1, 200.0);

					//glMatrixMode (GL_MODELVIEW);						
					//glLoadIdentity ();

					viewCam.update();								

					//see if we got a moon
					int pickedBody = viewPk.get_object(x, y, screenHeight - moonViewHeight);
					//printf("pb: %d\n", pickedBody);
					//set camera to follow the picked moon
					if (pickedBody && pickedBody != 1)
					{
						pickedBody--;

						Vec3f targ = *(sim->getOrbitalBody(pickedBody)->getLoc());
						const Vec3f* vel = sim->getOrbitalBody(pickedBody)->getVel();
						cam.moveToNewTarget(targ, vel, 80);
						followBodyIndex = pickedBody;
					}

					//reset the projection matrix
					glViewport (viewport[0], viewport[1], viewport[2],  viewport[3]);
					glMatrixMode (GL_PROJECTION);
					glLoadIdentity ();
					glMultMatrixf(proj_mat);
					glMatrixMode (GL_MODELVIEW);
					glLoadIdentity ();
					glMultMatrixf(modl_mat);
				}
			}//end if (state == 0)
		}//end if (button == 0)
	}//end if(targeting)
}

/*----------------------------------------------------------------------------*/
void Graphics::motionFunc(int x, int y) {
	//cout << "motionFunc: " << x << ", " << y << endl;
	if (targeting){
		targSphere.mouseDrag(x, y);
	}
	else{
		osd.checkDrag(x, y);
		if ( !cameraMoveMode ) { return; }
		cam.rotateWithMouse(x,y);
	}
}

/*----------------------------------------------------------------------------*/
void Graphics::passiveMotionFunc(int x, int y) {
	//cout << "passiveMotionFunc: " << x << ", " << y << endl;
	if (targeting){
		targSphere.mouseMove(x, y);
	}
	else{

	}
}

/*----------------------------------------------------------------------------*/
void Graphics::specialFunc(int key, int x, int y) {}


////////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
void Graphics::draw() {			

	drawStars();
	drawNebula();
	drawGravBodies();
}

void Graphics::drawViewScreen() {

	GravBody* body;
	Vec3f loc;

	if (!viewPk.isPicking()) {
		//save the current projection matrix
		glGetFloatv(GL_PROJECTION_MATRIX, proj_mat);
		//save the current model view matrix
		glGetFloatv(GL_MODELVIEW_MATRIX, modl_mat);
		//save the current viewport
		glGetIntegerv (GL_VIEWPORT, viewport);


		//set up the viewport and proj matrix
		//so we can render in 2D.
		glViewport (0, 0, screenWidth, moonViewHeight);
		glMatrixMode (GL_PROJECTION);
		glLoadIdentity ();
		gluPerspective(25.0, screenWidth/(float)moonViewHeight, 0.1, 200.0);

		glMatrixMode (GL_MODELVIEW);						
		glLoadIdentity ();

		viewCam.update();
	}


	float cur_loc = -lineupWidth/3;

	bodyMap* gravBodies = sim->getOrbitalBodyMap();
	bodyMap::iterator gbi;

	//for ( int i = 0; i < (int)gravBodies->size(); ++i) {
	for ( gbi = gravBodies->begin() ; gbi != gravBodies->end() ; ++gbi ) {
//	for (int i = 0; i < sim->getNumOrbitalBodies(); ++i)
//	{
		glPushMatrix(); {
			glTranslatef(-cur_loc, 0, 0);

			glPushMatrix(); {
				body = &gbi->second;//sim->getOrbitalBody(sim->getOrbitalBodyOrder(i));
				//gbi = gravBodies->find(sim->getOrbitalBodyOrder(i));
				//body= &gbi->second;

				glRotatef(-90, 1, 0, 0);
				glRotatef(body->getCurRotation(), 0, 0, 1);				
				glRotatef(90, 1, 0, 0);
				glRotatef(body->getRotationAxis(), 0, 1, 0);

				glMaterialfv( GL_FRONT, GL_AMBIENT, mids );
				glMaterialfv( GL_FRONT, GL_EMISSION, zeros );
				glMaterialfv( GL_FRONT, GL_DIFFUSE, blues);

				viewPk.load_object(body->getID()+1);

				drawGeosphere(body->getRad(), 4);			
			} glPopMatrix();

		} glPopMatrix();

		cur_loc += 1 + body->getRad();
	}


	if (!viewPk.isPicking()) {
		//reset the projection matrix
		glViewport (viewport[0], viewport[1], viewport[2],  viewport[3]);
		glMatrixMode (GL_PROJECTION);
		glLoadIdentity ();
		glMultMatrixf(proj_mat);
		glMatrixMode (GL_MODELVIEW);
		glLoadIdentity ();
		glMultMatrixf(modl_mat);
	}
}

/*----------------------------------------------------------------------------*/
void Graphics::drawStars() {

	if ( dlStars != -1 ) {
		glDisable(GL_TEXTURE_2D);
		glCallList(dlStars);
		glEnable(GL_TEXTURE_2D);
		return;
	}

	dlStars = glGenLists(1);
	glNewList(dlStars, GL_COMPILE);

		for ( register unsigned int i = 0 ; i < numStars ; i++ ) {

			glMaterialfv( GL_FRONT, GL_AMBIENT, ones );
			glMaterialfv( GL_FRONT, GL_EMISSION, stars[i].getDiffuse() );
			glMaterialfv( GL_FRONT, GL_DIFFUSE, stars[i].getDiffuse() );

			const Vec3f* loc = stars[i].getLoc();
			
			glPointSize((float)stars[i].getSize());

			glBegin(GL_POINTS);
				glVertex3f( loc->x, loc->y, loc->z );
			glEnd();
		}

	glEndList();
}

/*----------------------------------------------------------------------------*/
void Graphics::drawNebula() {

	glPushMatrix(); {
		glBindTexture(GL_TEXTURE_2D, nebulaT);
		//glTranslatef(0, 0, 0);
		
		gluQuadricOrientation (nebulaSphere, GLU_INSIDE);
		gluQuadricTexture (nebulaSphere, true);              	
		gluQuadricDrawStyle(nebulaSphere, GLU_FILL);
		gluSphere(nebulaSphere, 900, 20, 20);
	}glPopMatrix();

}

/*----------------------------------------------------------------------------*/
void Graphics::drawPickingSpheres() { 

	GravBody* body;
	Vec3f loc;

	bodyMap* gravBodies = sim->getOrbitalBodyMap();
	bodyMap::iterator gbi;

	for ( gbi = gravBodies->begin() ; gbi != gravBodies->end() ; ++gbi ) {
		body = &(gbi->second);//sim->getOrbitalBody(i);
		if (body->getID() == 0)
			continue;

		loc = body->getGfxLoc();

		glPushMatrix(); {
			glTranslatef(loc.x, loc.y, loc.z);
			//draw an invisible sphere around the moons for easier picking
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glColor4f(0,0,0,0);			
			q1 = gluNewQuadric();
			gluQuadricOrientation (q1, GLU_OUTSIDE);
			gluQuadricDrawStyle(q1, GLU_FILL);
			//set a gl number for the grav body
			pk.load_object(body->getID()+1);
			gluSphere(q1, 4, 12, 12);
			glEnable(GL_LIGHTING);
			glEnable(GL_TEXTURE_2D);
		} glPopMatrix();
	}

}

/*----------------------------------------------------------------------------*/
void Graphics::drawGravBodies() { 

	GravBody* body;
	Vec3f loc;

	bodyMap* gravBodies = sim->getOrbitalBodyMap();
	bodyMap::iterator gbi;

	for ( gbi = gravBodies->begin() ; gbi != gravBodies->end() ; ++gbi ) {

		body = &(gbi->second);//sim->getOrbitalBody(i);
		loc = body->getGfxLoc();
		float dist = (loc-cam.getEyePos()).length();

		glPushMatrix(); {

			glTranslatef(loc.x, loc.y, loc.z);

			glPushMatrix(); {

				glRotatef(body->getCurRotation(), 0, 0, 1);				
				glRotatef(90, 1, 0, 0);
				glRotatef(body->getRotationAxis(), 0, 1, 0);

				glMaterialfv( GL_FRONT, GL_AMBIENT, mids );
				glMaterialfv( GL_FRONT, GL_EMISSION, zeros );
				glMaterialfv( GL_FRONT, GL_DIFFUSE, blues);

				int detailLevel = body->getMaxDetail()-(int)(dist*0.06);
				if ( detailLevel < 2 ) { detailLevel = 2; }

				//set a gl number for the grav body
				pk.load_object(body->getID()+1);

				glDisable(GL_BLEND);
				drawGeosphere( body->getRad(), detailLevel );
				glEnable(GL_BLEND);
				

			} glPopMatrix();

			drawGeosphereHistory( body, &loc );		

		} glPopMatrix();
	}

	//draw debris
	bodyMap* debrisBodies = sim->getDebrisBodyMap();
	bodyMap::iterator dbi;

	for ( dbi = debrisBodies->begin() ; dbi != debrisBodies->end() ; ++dbi ) {

		body = &(dbi->second);//sim->getDebrisBody(i);
		loc = body->getGfxLoc();
		float dist = (loc-cam.getEyePos()).length();

		glPushMatrix();

			glTranslatef(loc.x, loc.y, loc.z);
			glMaterialfv( GL_FRONT, GL_AMBIENT, mids );
			glMaterialfv( GL_FRONT, GL_EMISSION, zeros );
			glMaterialfv( GL_FRONT, GL_DIFFUSE, blues);

			int detailLevel = 2;
			//if ( detailLevel < 2 ) { detailLevel = 2; }
			
			//set a gl number for the grav body
			pk.load_object(0);
			
			drawGeosphere(body->getRad(), detailLevel);
			drawGeosphereDebrisHistory(body, &loc );

		glPopMatrix();
	}

	//draw missiles
	missileMap* missileBodies = sim->getMissileBodyMap();
	missileMap::iterator mbi;

	MissileBody* mBody;
	for ( mbi = missileBodies->begin() ; mbi != missileBodies->end() ; ++mbi ) {
		mBody = &(mbi->second);
		if (mBody->getMMass() == 0)
			continue;

		loc = *(mBody->getMLoc());

		glPushMatrix(); {		
			glMaterialfv( GL_FRONT, GL_AMBIENT, reds );
			glMaterialfv( GL_FRONT, GL_EMISSION, mids );
			glMaterialfv( GL_FRONT, GL_DIFFUSE, reds);
			glPointSize((float)5);

			glBegin(GL_POINTS);
				glVertex3f( loc.x, loc.y, loc.z );
			glEnd();
		}glPopMatrix();
	}
	
}

/*----------------------------------------------------------------------------*/
void Graphics::createGeosphereDisplayLists() {
	int detailLevels = 5;
	Geosphere g = Geosphere(1, detailLevels);

	dlGeo = glGenLists(detailLevels);
	
	for ( int dl = 0 ; dl < detailLevels ; dl++ ) {
		glNewList(dlGeo+dl, GL_COMPILE);
			glBegin(GL_TRIANGLES);
				for ( int i = 0 ; i < g.getNumFaces() ; i++ ) {			
					drawGeosphereFace(g.getFace(i), dl);
				}
			glEnd();
		glEndList();
	}
}

/*----------------------------------------------------------------------------*/
void Graphics::drawGeosphere(float rad, int detailLevels) {
	glScalef(rad,rad,rad);
	glCallList(dlGeo+detailLevels-1);
}

/*----------------------------------------------------------------------------*/
void Graphics::drawGeosphereFace(GeosphereFace* face, int levelsLeft) {
	
	if ( face->getIsDivided() && levelsLeft > 0 ) {
		for ( register char i = 0 ; i < 4 ; i++ ) { 
			drawGeosphereFace(face->getFace(i), levelsLeft-1);
		}
		return;
	}

	// Skip backfacing triangles
	if ( view * (*(face->getFaceNorm())) < -0.2 ) { return; }
	
	glBindTexture( GL_TEXTURE_2D, moonTexture );

	for ( register char i = 0 ; i < 3 ; i++ ) {
		const GeosphereVert* v = face->getVert(i);
		glTexCoord2d(v->texU, v->texV);
		glNormal3f(v->norm.x,v->norm.y,v->norm.z);
		glVertex3f(v->vert.x,v->vert.y,v->vert.z);
	}
}

/*----------------------------------------------------------------------------*/
void Graphics::drawGeosphereHistory( GravBody* gravBody, const Vec3f* loc ) {
	
	// Use a semaphore to avoid sync exceptions
	//gravBody->getHistoryAccess(true);
	list<Vec3f> h = *gravBody->getHistory();
	list<Vec3f> f = *gravBody->getFuture();
	//gravBody->getHistoryAccess(false);

	list<Vec3f>::iterator i;
	alphas[3] = 1.0;
	glMaterialfv( GL_FRONT, GL_AMBIENT, ones );
	glMaterialfv( GL_FRONT, GL_EMISSION, ones );
	float alphaStep = 1.0f/h.size();
	
	glBegin(GL_LINE_STRIP);

		glMaterialfv( GL_FRONT, GL_DIFFUSE, alphas);
		glVertex3f(0,0,0);

		for ( i = h.begin() ; i != h.end() ; ++i ) {
			alphas[3] -= alphaStep;
			glMaterialfv( GL_FRONT, GL_DIFFUSE, alphas);
			Vec3f pos = *i;
			glVertex3f(pos.x-loc->x, pos.y-loc->y, pos.z-loc->z);
		}			

	glEnd();


	//display the future path
	alphas[3] = 1.0;
	alphaStep = 1.0f/f.size();

	glBegin(GL_LINE_STRIP);
	{
		glMaterialfv( GL_FRONT, GL_AMBIENT, reds );
		glMaterialfv( GL_FRONT, GL_EMISSION, reds );

		for (i = f.begin(); i != f.end(); ++i) {
			alphas[3] -= alphaStep;
			glMaterialfv( GL_FRONT, GL_DIFFUSE, alphas);
			Vec3f pos = *i;			
			
			glVertex3f(pos.x-loc->x, pos.y-loc->y, pos.z-loc->z);
		}
	}
	glEnd();
}

/*----------------------------------------------------------------------------*/
void Graphics::drawGeosphereDebrisHistory( GravBody* gravBody, const Vec3f* loc ) {
	
	// Use a semaphore to avoid sync exceptions
	//gravBody->getHistoryAccess(true);
	list<Vec3f> h = *gravBody->getHistory();
	//gravBody->getHistoryAccess(false);

	list<Vec3f>::iterator i;
	alphas[3] = 1.0;
	glMaterialfv( GL_FRONT, GL_AMBIENT, mids );
	glMaterialfv( GL_FRONT, GL_EMISSION, blues );
	float alphaStep = 3.0f/h.size();
	
	glBegin(GL_LINE_STRIP);

		glMaterialfv( GL_FRONT, GL_DIFFUSE, blues);
		glVertex3f(0,0,0);

		for ( i = h.begin() ; i != h.end() ; ++i ) {
			alphas[3] -= alphaStep;
			glMaterialfv( GL_FRONT, GL_DIFFUSE, alphas);
			Vec3f pos = *i;
			glVertex3f(pos.x-loc->x, pos.y-loc->y, pos.z-loc->z);
		}

	glEnd();
}



